package server;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;

import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;

public class RandomizedServer {
	
	private static final int BAR_LENGTH = 20;
	private static final String ADD = " <-- ";
	private static final String REMOVE = " --> ";
	
	private long id = 0;
	
	private int runningJobs = 0;
	private int executedJobs = 0;
	private int maxJobs = 0;
	private float prob = 1;
	
	private Queue queue;
	private QueueConnectionFactory qcf;
	private QueueConnection qc;
	private QueueSession qs;
	private QueueReceiver qrec;
	
	private RandomizedLogger logger;
	
	
	public RandomizedServer(int maxJobs) throws Exception {
		this.maxJobs = maxJobs;
		Properties properties = new Properties();
		properties.put("java.naming.factory.initial", "fr.dyade.aaa.jndi2.client.NamingContextFactory");
		properties.put("java.naming.factory.host", "localhost");
		properties.put("java.naming.factory.port", "16400");
		Context ictx = new InitialContext(properties);
		
		queue = (Queue) ictx.lookup("queue");
		qcf = (QueueConnectionFactory) ictx.lookup("qcf");

		ictx.close();

		qc = qcf.createQueueConnection();
		qs = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	    qrec = qs.createReceiver(queue);
	    
	    id = new Date().getTime();
	    
	    logger = new RandomizedLogger(this);
	    
	}
	
	public void start() throws Exception {
		qc.start();
		logger.start();
	}
	
	public QueueConnection getQueueConnection() {
		return qc;
	}
	
	public QueueReceiver getQueueReceiver() {
		return qrec;
	}
	
	public void printLoad(String job, String action) {
		DecimalFormat fmt = new DecimalFormat("0.0", new DecimalFormatSymbols(Locale.UK));
		
		double perc = (double) runningJobs / maxJobs;
		int fill = (int) ((float) BAR_LENGTH*perc);
		
		System.out.print(fmt.format(perc*100.0)+"% \t[");
		for(int i=0; i<fill; i++) {
			if(i==BAR_LENGTH-1) {
				System.out.print("#]");
			} else {
				System.out.print("#|");
			}
		}
		
		for(int i=0; i<BAR_LENGTH-fill; i++) {
			if(i==BAR_LENGTH-fill-1) {
				System.out.print(" ]");
			} else {
				System.out.print(" |");
			}
		}
		System.out.print(action+job);
		System.out.println(" [queued:" + runningJobs + " - accepted:" + executedJobs + "]");
	}
	
	public synchronized void addJob(String job) {
		runningJobs++;
		executedJobs++;
		printLoad(job, ADD);
		setProb(runningJobs);
	}
	
	public synchronized void removeJob(String job) {
		runningJobs--;
		printLoad(job, REMOVE);
		setProb(runningJobs);
	}
	
	public int getRunningJobs() {
		return runningJobs;
	}
	
	public void setProb(int runningJobs) {
		prob = (float) (maxJobs-runningJobs) / maxJobs;
	}
	
	public float getProb() {
		return prob;
	}
	
	public long getId() {
		return this.id;
	}
	
}
